import json
import traceback
from PIL import Image, ImageDraw, ImageFont, ImageFilter
from flask import make_response,render_template, session,Blueprint,redirect
from flask import request,jsonify
from io import BytesIO
from datetime import timedelta
import datetime
import random
import os
import config
from config import makeNewSession, generate_token
from hashlib import md5
import models

login = Blueprint('login',__name__)
font_file = os.path.join(config.STATIC_PATH,"font","arial.ttf")


def check_code(width=120, height=30, char_length=5,  font_file=font_file,font_size=28):
    code = []
    img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255))
    draw = ImageDraw.Draw(img, mode='RGB')

    def rndChar():
        """
        生成随机字母
        :return:
        """
        return chr(random.randint(65, 90))

    def rndColor():
        """
        生成随机颜色
        :return:
        """
        return (random.randint(0, 255), random.randint(10, 255), random.randint(64, 255))

    # 写文字
    font = ImageFont.truetype(font_file, font_size)
    for i in range(char_length):
        char = rndChar()
        code.append(char)
        h = random.randint(0, 4)
        draw.text([i * width / char_length, h], char, font=font, fill=rndColor())

    # 写干扰点
    for i in range(40):
        draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())

    # 写干扰圆圈
    for i in range(40):
        draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor())
        x = random.randint(0, width)
        y = random.randint(0, height)
        draw.arc((x, y, x + 4, y + 4), 0, 90, fill=rndColor())

    # 画干扰线
    for i in range(5):
        x1 = random.randint(0, width)
        y1 = random.randint(0, height)
        x2 = random.randint(0, width)
        y2 = random.randint(0, height)

        draw.line((x1, y1, x2, y2), fill=rndColor())

    img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)
    return img, ''.join(code)


def getImgCode():
    image, code = check_code()
    # 图片以二进制形式写入
    buf = BytesIO()
    image.save(buf, 'jpeg')
    buf_str = buf.getvalue()
    # 把buf_str作为response返回前端，并设置首部字段
    response = make_response(buf_str)
    response.headers['Content-Type'] = 'image/gif'
    # 将验证码字符串储存在session中
    session['imageCode'] = code
    return response

@login.route("/loginPage/ImgCode",methods=['GET'])
def ImgCode():
    return getImgCode()


@login.route("/loginPage", methods=['GET','POST'])
def loginPage():
    if request.method == "GET":
        return render_template("login.html")
    elif request.method == "POST":
        username = request.form.get('username')
        password = request.form.get('password')
        captcha = request.form.get('captcha').lower()

        session_q = makeNewSession()

        user = session_q.query(models.User).filter(models.User.userID==username).first()
        session_q.close()
        if not user or user.password != password:
            return jsonify({"code":-1, "msg": "用户名或密码错误"})
            
        if captcha == session.get("imageCode").lower():
            expire = 7*24*3600
            return jsonify({'code':0,'msg':'登录成功', 'cookies': {
                "user":username,
                "token": generate_token(config.TOKEN_KEY,expire)
            },
            "expires":expire
            })
        else:
            return jsonify({'code':-1,'msg':'图片验证码错误'})

# 修改登录密码
@login.route("/changePwd", methods=['POST'])
def changePwd():
    user = request.cookies.get("user")
    if not user:
        return redirect("/loginPage")
    print("request form ",request.form)
    print("request json ",request.get_data(as_text=True))
    # get_data = request.get_json()
    pwd_old = request.form.get("old_password")
    pwd_new = request.form.get("new_password")

    session = makeNewSession()
    usr = session.query(models.User).filter(models.User.userID==user.strip()).first()
    if not usr or usr.password != pwd_old: 
        session.close()
        return jsonify({"code":-1, "msg": "验证错误"})
    usr.password = pwd_new
    session.add(usr)
    session.commit()
    session.close()
    return jsonify({"code":0, "msg": "密码修改成功"})

# 获取配置参数
@login.route("/get_settings", methods=['POST'])
def get_settings():
    session = makeNewSession()
    settings_all = session.query(models.Setting).all()
    session.close()
    adict = {}
    for setting in settings_all:
        if setting.type == "str":
            adict[setting.keyname] = setting.value
        elif setting.type == "int":
            adict[setting.keyname] = int(setting.value)
        elif setting.type == "float":
            adict[setting.keyname] = float(setting.value)
        elif setting.type == "Iterable":
            adict[setting.keyname] = json.loads(setting.value)
        else:
            adict[setting.keyname] = setting.value
    return jsonify(adict)

# 修改配置参数
@login.route("/update_settings", methods=['POST'])
def update_settings():
    get_data = request.get_json()
    if not get_data: return "no args",406
    session = makeNewSession()
    msg = []
    
    for k in get_data:
        try:
            session.query(models.Setting).filter(models.Setting.keyname==k).update({models.Setting.value:get_data[k]})
            msg.append(f"{k} 修改成功!")
            code = 0
        except:
            msg.append(f"{k} 修改失败")
            code = -1
            traceback.print_exc()

    session.commit()
    session.close()
    return jsonify({"code":code,"msg":msg})
